package com.example.pingze.controller;

import com.example.pingze.entity.Sentence;
import com.example.pingze.exception.PingZeException;
import com.example.pingze.service.SentenceService;
import com.example.pingze.utils.ResultVOUtils;
import com.example.pingze.vo.Result;
import org.apache.commons.text.similarity.CosineSimilarity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/sentence")
@CrossOrigin(origins = "*")
public class SentenceController {
    @Autowired
    private SentenceService service;
    @Autowired
    private RedisTemplate redisTemplate;
    //通过诗人名获取名句
    @PostMapping("/getSentencesByName")
    public Result<List<Sentence>> getSentencesByName(@RequestParam String sentenceFrom){
        if(sentenceFrom == null){
            throw new PingZeException("诗人名称为空");
        }
        List<Sentence> list = service.getSentences(sentenceFrom);
        return ResultVOUtils.result(list);
    }
    //获取通过诗人和诗名获取名句
    @PostMapping("/getSentence")
    public Result<Sentence> getSentences(@RequestParam String writer,
                                         @RequestParam String title){
        //多条件查询一条名句信息
        if(writer == null){
            throw new PingZeException("作者信息为空");
        }
        if(title == null){
            throw new PingZeException("诗名为空");
        }
        List<Sentence> list = service.getSentences(writer);
        Sentence s = new Sentence();
        for(Sentence sentence : list){
            if(sentence.getSentenceFrom().contains(title)){
                s = sentence;
            }
        }
        String id = s.getId();
        return ResultVOUtils.success(id);
    }
    //获取sentence，20条
    @PostMapping("/getSentenceList")
    public List<Sentence> getSentenceList(
            @RequestParam(name = "pageNum",required = false, defaultValue = "1") Integer pageNum,
            @RequestParam(name = "pageSize", required = false, defaultValue = "8") Integer pageSize
    ){
        if(pageNum < 1){
            throw new PingZeException("页码不能小于1");
        }
        Pageable pageable = PageRequest.of(pageNum - 1, pageSize);
        Page page = service.getSentenceList(pageable);
        List content = page.getContent();
        return content;
    }

    //=================================================================================================

    /**
     * 飞花令
     *
     * 测试：UUID-----293276b9-4e17-4a41-9e01-4b9b7fcc8e10
     */


    /**
     * 通过关键字查询相关sentence - 返回值为含有关键字的一句诗
     */
    @PostMapping("/getSentenceByKeyword")
    public Result getSentence(@RequestParam String keyword,
                              @RequestParam String account) {
        if (keyword == null){
            throw new PingZeException("关键字为空");
        }
        if (account == null){
            throw new PingZeException("账号为空");
        }
        List<Sentence> sentences = service.findSentencesBySentence(keyword);
        int len = sentences.size();
        Random rand = new Random();
        // 生成一个随机数，范围在0~list.size()
        int num = rand.nextInt(len);
        Sentence sentence = sentences.get(num);
        String key = "Feihualing:" + account;

        Double score = redisTemplate.opsForZSet().score(key, sentence.getSentence());
        if(null != score){
            //表示该账号的该条历史记录已经存在
            return ResultVOUtils.success("该诗句已重复，再想一想其他的诗句吧~");
        }
        redisTemplate.opsForZSet().add(key, sentence.getSentence(), System.currentTimeMillis());
        return ResultVOUtils.result(sentence.getSentence());
    }

    /**
     * 游戏结束,通过account,获取历史记录
     *
     * 13785292564:293276b9-4e17-4a41-9e01-4b9b7fcc8e10
     */
    @PostMapping("/getHistoricalRecords")
    public Result getHistoricalRecords(@RequestParam String account){
        if (account == null){
            throw new PingZeException("用户账号为空");
        }
        String key = "Feihualing:" + account;
        System.out.print(key);
        Set<String> members = redisTemplate.opsForZSet().range(key,0,-1);
        members.stream().forEach(element->System.out.println(element));
        return ResultVOUtils.result(members);
    }

    /**
     * 判断
     *
     * 1、传来的诗句在数据库表中进行模糊查询（查不到抛异常）
     * 2、截取诗句，判断传来的诗句是否符合要求
     * 3、对传来的诗句进行相似度匹配（>0.6）
     * 4、如果能正确匹配，将诗句存入缓存中，返回正确的响应
     */
    @PostMapping("/verifySentence")
    public Result verifySentence(@RequestParam String account,
                                 @RequestParam String answer,
                                 @RequestParam String keyword){
        if (account == null){
            throw new PingZeException("账号为空");
        }
        if (answer == null){
            throw new PingZeException("用户回复诗句信息为空");
        }
        if (keyword == null){
            throw new PingZeException("关键字为空");
        }
        // 1、判断用户输入的诗句中是否包含关键字
        if (!answer.contains(keyword)) {
            return ResultVOUtils.error("该诗句不符合关键字要求，请输入符合规则的诗句");
        }else {
            // 2、模糊查询，对用户输入的诗句进行模糊查询
            Sentence sentence = service.findSentenceBySentence(answer);
            if (sentence == null){
                return ResultVOUtils.error("该诗句在数据库中没有对应的古诗");
            }else {
                // 获取诗句
                String s = sentence.getSentence();
                String[] sentenceList = s.split("，");
                if (answer.length() < sentenceList[0].length()){
                    System.out.println(sentenceList[0]);
                    return ResultVOUtils.error("诗句太短啦，想好再发送哦");
                }else {
                    double similarity = getSimilarity(answer, s);
                    if (similarity >= 0.55){
                        String key = "Feihualing:" + account;
                        Double score = redisTemplate.opsForZSet().score(key, answer);
                        if(null != score){
                            //表示该账号的该条历史记录已经存在
                            return ResultVOUtils.error("该诗句已重复，再想一想其他的诗句吧~");
                        }
                        redisTemplate.opsForZSet().add(key, answer, System.currentTimeMillis());
                        return ResultVOUtils.success("回答正确，太棒啦！");
                    }else {
                        return ResultVOUtils.error("再试一次");
                    }
                }
            }
        }
    }

    private double getSimilarity(String answer, String s) {
        Map<CharSequence, Integer> map = Arrays.stream(answer.split(""))
                .collect(Collectors.toMap(c -> c, c -> 1, Integer::sum));
        Map<CharSequence, Integer> map2 = Arrays.stream(s.split(""))
                .collect(Collectors.toMap(c -> c, c -> 1, Integer::sum));
        CosineSimilarity cosineSimilarity = new CosineSimilarity();
        return cosineSimilarity.cosineSimilarity(map, map2);
    }


    //================================================================================================================



    /**
     * 后台管理系统
     * @param sentence
     * @param pageCode
     * @param pageSize
     * @return
     */
    @CrossOrigin
    @PostMapping("/page")
    public Result<Page<Sentence>> getList(
            Sentence sentence,
            @RequestParam(name = "pageCode", required = false, defaultValue = "1") Integer pageCode,
            @RequestParam(name = "pageSize", required = false, defaultValue = "2") Integer pageSize
    ){
        if(pageCode < 1){
            throw new PingZeException("页码不能小于1");
        }
        Sort.Order idOrder = Sort.Order.asc("id");
        Sort sort = Sort.by(idOrder);
        Pageable pageable = PageRequest.of(pageCode - 1, pageSize, sort);
        Page page = service.findSentenceList(sentence, pageable);
        return ResultVOUtils.result(page);
    }
    @CrossOrigin
    @PostMapping("/add")
    public Result<Sentence> add(String sentence, String sentenceFrom){
        Sentence add = service.add(sentence, sentenceFrom);
        return ResultVOUtils.result(add);
    }
    @CrossOrigin
    @PostMapping("/edit")
    public Result<Sentence> edit(String id, String sentence, String sentenceFrom){
        Sentence edit = service.edit(id, sentence, sentenceFrom);
        return ResultVOUtils.result(edit);
    }
    @CrossOrigin
    @Transactional
    @PostMapping("/delete")
    public Result<String> delete(String id){
        if(id == null){
            throw new PingZeException("id为空");
        }
        Sentence sentence = service.findSentenceById(id);
        if(sentence != null){
            service.delete(sentence);
        }
        return ResultVOUtils.success("delete successful");
    }
}
